package com.jtpay.sdk.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import apiUtils.models.util.ModelFilterAble;

/**
 * 包含过滤功能和选中item功能
 * 如果使用过滤功能需要将索要过滤的类的toString方法重写，描述所要过滤的数据
 * 实现ModelFilterAble接口
 * <p>
 * Created by Administrator on 2017/8/22.
 */

public abstract class BaseRecycleAdapter<E> extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
    private final Object mLock = new Object();
    protected List<E> mList = new ArrayList<>();
    protected LayoutInflater mLayoutInflater;
    private List<E> mSource = new ArrayList<>();
    private Filter mFilter;
    private int mSelectPosition = -1;
    private HashMap<String, FilterValue> mFilterValues = new HashMap<String, FilterValue>();
    private OnSelectItemListener mListener;

    public BaseRecycleAdapter() {
    }

    public void setListener(OnSelectItemListener listener) {
        mListener = listener;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mLayoutInflater == null) {
            mLayoutInflater = LayoutInflater.from(parent.getContext());
        }
        return createView(parent, viewType);
    }

    protected abstract RecyclerView.ViewHolder createView(ViewGroup parent, int type);

    public void setData(List<E> list) {
        mList.clear();
        if (list != null && !list.isEmpty()) {
            mList.addAll(list);
        }
        if (mSource.isEmpty()) {
            mSource = list;
        }
        notifyDataSetChanged();
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
        setView(viewHolder, position);
        if (position == mSelectPosition) {
            selected(viewHolder, position);
        } else {
            unSelected(viewHolder, position);
        }
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mSelectPosition = position;
                if (mListener != null) {
                    mListener.selectItem(mSelectPosition);
                }
                notifyDataSetChanged();
            }
        });
    }

    protected void unSelected(RecyclerView.ViewHolder holder, int position) {

    }

    protected void selected(RecyclerView.ViewHolder holder, int position) {

    }

    protected abstract void setView(RecyclerView.ViewHolder holder, int position);

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public int getSelectPosition() {
        return mSelectPosition;
    }

    public E getSelecteData() {
        if (mSelectPosition < mList.size() && mSelectPosition >= 0) {
            return mList.get(mSelectPosition);
        }
        return null;
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new MyFilter();
        }
        return mFilter;
    }

    public interface OnSelectItemListener {
        void selectItem(int position);
    }

    class MyFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            E data = getSelecteData();
            FilterResults results = new FilterResults();
            if (constraint == null || constraint.length() == 0) {
                final List<E> list;
                synchronized (mLock) {
                    list = new ArrayList<>(mSource);
                }
                for (int i = 0; i < list.size(); i++) {
                    if (data == list.get(i)) {
                        mSelectPosition = i;
                    }
                }
                results.values = list;
                results.count = list.size();
            } else {
                final String prefixString = constraint.toString();
                final ArrayList<E> values;
                synchronized (mLock) {
                    values = new ArrayList<>(mSource);
                }

                final int count = values.size();
                ArrayList<E> newValues = new ArrayList<>();
                for (int i = 0; i < count; i++) {
                    final E value = values.get(i);
                    if (value instanceof ModelFilterAble) {
                        String content = ((ModelFilterAble) values.get(i)).getFilterData();
                        if (!mFilterValues.containsKey(content)) {
                            mFilterValues.put(content, new FilterValue(content));
                        }
                        FilterValue filterValue = mFilterValues.get(content);
                        if (filterValue.filter(prefixString))
                            newValues.add(value);
                    }
                }
                for (int i = 0; i < newValues.size(); i++) {
                    if (data == newValues.get(i)) {
                        mSelectPosition = i;
                    }
                }
                results.values = newValues;
                results.count = newValues.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mList.clear();
            if (results.values != null)
                mList.addAll((Collection<? extends E>) results.values);
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                if (constraint.length() != 0) {
                    notifyDataSetChanged();
                    return;
                }
                setData(mSource);
            }
        }
    }

    class FilterValue {
        HanyuPinyinOutputFormat mFormat = new HanyuPinyinOutputFormat();
        private String mResourceContent;
        private String mCompleteSellContent;
        private String mAcronymSpellContent;

        public FilterValue(String resourceContent) {
            resourceContent = resourceContent.toLowerCase();
            init();
            this.mResourceContent = resourceContent;
            mCompleteSellContent = getPinYin(resourceContent);
            mAcronymSpellContent = getAcronymPinYin(resourceContent);
        }

        private void init() {
            mFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            mFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        }

        private String getAcronymPinYin(String resourceContent) {
            StringBuffer valueBuffer = new StringBuffer();
            for (int j = 0; j < resourceContent.length(); j++) {
                char c = resourceContent.charAt(j);
                try {
                    String[] strings = PinyinHelper.toHanyuPinyinStringArray(c, mFormat);
                    if (strings == null) {
                        valueBuffer.append(c);
                    } else {
                        valueBuffer.append(strings[0].charAt(0));
                    }
                } catch (BadHanyuPinyinOutputFormatCombination combination) {
                    combination.printStackTrace();
                }
            }
            return valueBuffer.toString();
        }

        private String getPinYin(String resourceContent) {
            StringBuffer valueBuffer = new StringBuffer();
            for (int j = 0; j < resourceContent.length(); j++) {
                char c = resourceContent.charAt(j);
                try {
                    String[] strings = PinyinHelper.toHanyuPinyinStringArray(c, mFormat);
                    if (strings == null) {
                        valueBuffer.append(c);
                    } else {
                        valueBuffer.append(strings[0]);
                    }
                } catch (BadHanyuPinyinOutputFormatCombination combination) {
                    combination.printStackTrace();
                }
            }
            return valueBuffer.toString();
        }

        public boolean filter(String prefixString) {
            prefixString = prefixString.toLowerCase();
            if (mResourceContent.contains(prefixString) || mCompleteSellContent.contains(prefixString) || mAcronymSpellContent.contains(prefixString)) {
                return true;
            }
            return false;
        }
    }
}